﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SLogo.Command;
using SLogo.Compile;
using SLogo.Helper;

namespace SLogo.Execute
{
    /// <summary>
    /// 解释执行中间代码的类
    /// </summary>
    class ExecuteSlogo
    {
        //符号表
        private static List<Variable> _symbolList = new List<Variable>();
        //自定义过程只能先定义后使用，这个变量保存已经定义了的过程的最大序号
        private static int _customProcessListTop = 0;
        //符号表中变量的数目
        private static int _symbolNum = 0;

        /// <summary>
        /// 执行指定的中间代码列表
        /// </summary>
        /// <param name="intermediateCodes">中间代码表</param>
        /// <returns>是否成功</returns>
        public static bool ExecuteAll(List<IntermediateCode> intermediateCodes)
        {
            for (int i = 0; i < intermediateCodes.Count;i++)
            {
                if (intermediateCodes[i].Operator == "stop")
                {
                    if (intermediateCodes[i].Arguments.Count == 0)
                    {
                        return true; //正确遇到stop命令
                    }
                    ConsoleHelper.StdErr(String.Format("运行时错误：stop命令不能带参数\n\t错误位置：{0} line {1}\n",
                                                       intermediateCodes[i].FileName,
                                                       intermediateCodes[i].Line));
                    return false;
                }
                if (intermediateCodes[i].Operator == "#goto") //goto X
                {
                    i = (int)intermediateCodes[i].Arguments[0].NumberValue - 1;
                    continue;
                }
                if (intermediateCodes[i].Operator == "if") //if X goto X
                {
                    if (intermediateCodes[i].Arguments[0].TheType == Agument.ArgumentType.Number &&
                        intermediateCodes[i].Arguments[0].NumberValue == 1 ||
                        intermediateCodes[i].Arguments[0].TheType == Agument.ArgumentType.Variable &&
                        GetVariable(intermediateCodes[i].Arguments[0].VariableValue) &&
                        intermediateCodes[i].Arguments[0].VariableValue.NumberValue == 1) //if X
                    {
                        i = (int) intermediateCodes[i].Arguments[1].NumberValue - 1; //goto X
                    }
                    continue;
                }
                if (!ExecuteACommand(intermediateCodes[i])) //命令执行失败
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 执行自定义过程
        /// </summary>
        /// <param name="customProcessName">过程名</param>
        /// <param name="realArguments">实参列表</param>
        /// <returns></returns>
        public static bool ExecuteCustomProcess(String customProcessName, List<Agument> realArguments)
        {
            CustomProcess customProcess = null;
            for (int i = 0; i < _customProcessListTop; i++) //在已经定义的过程中查找名称相同的过程
            {
                if (SyntaxAndSemanticAnalysis.CustomProcessList[i].Name == customProcessName)
                {
                    customProcess = SyntaxAndSemanticAnalysis.CustomProcessList[i];
                }
            }
            if (customProcess != null) //如果查找到的过程不为空
            {
                //获取外层过程定义的临时变量
                List<Variable> outer = _symbolList.GetRange(0, _symbolList.Count - _symbolNum);
                List<Variable> outerSymbol = new List<Variable>();
                foreach (Variable o in outer)
                {
                    Variable v = new Variable(o.Name);
                    v.NumberValue = o.NumberValue;
                    v.StringValue = o.StringValue;
                    v.TheType = o.TheType;
                    outerSymbol.Add(v);
                }
                if (customProcess.UpdateArguments(realArguments)) //如果成功填充参数的值
                {
                    //从符号表中删除外层临时变量
                    for (int i = outerSymbol.Count; i > 0; i--)
                    {
                        _symbolList.RemoveAt(0);
                    }
                    //添加局部变量到符号表的前边以得到优先搜索
                    List<Variable> symbolTemp = customProcess.Arguments.GetRange(0, customProcess.Arguments.Count);
                    symbolTemp.AddRange(_symbolList);
                    _symbolList = symbolTemp;
                    //执行过程段
                    for (int i = 0; i < customProcess.CodeBlock.Count; i++)
                    {
                        if (customProcess.CodeBlock[i].Operator == "stop")
                        {
                            if (customProcess.CodeBlock[i].Arguments.Count == 0)
                            {
                                break; //正确遇到stop命令
                            }
                            ConsoleHelper.StdErr(String.Format("运行时错误：stop命令不能带参数\n\t错误位置：{0} line {1}\n",
                                                               customProcess.CodeBlock[i].FileName,
                                                               customProcess.CodeBlock[i].Line));
                            return false;
                        }
                        if (customProcess.CodeBlock[i].Operator == "#goto") //goto X
                        {
                            i = (int) customProcess.CodeBlock[i].Arguments[0].NumberValue - 1;
                            continue;
                        }
                        if (customProcess.CodeBlock[i].Operator == "if") //if X goto X
                        {
                            if (customProcess.CodeBlock[i].Arguments[0].TheType == Agument.ArgumentType.Number &&
                                customProcess.CodeBlock[i].Arguments[0].NumberValue == 1 ||
                                customProcess.CodeBlock[i].Arguments[0].TheType == Agument.ArgumentType.Variable &&
                                GetVariable(customProcess.CodeBlock[i].Arguments[0].VariableValue) &&
                                customProcess.CodeBlock[i].Arguments[0].VariableValue.NumberValue == 1) //if X
                            {
                                i = (int) customProcess.CodeBlock[i].Arguments[1].NumberValue - 1; //goto X
                            }
                            continue;
                        }
                        
                        if (!ExecuteACommand(customProcess.CodeBlock[i])) //命令执行失败
                        {
                            return false;
                        }
                    }
                    //恢复符号表
                    for (int i = customProcess.Arguments.Count; i > 0; i--)
                    {
                        _symbolList.RemoveAt(0);
                    }
                    //恢复外层临时变量
                    outerSymbol.AddRange(_symbolList);
                    _symbolList = outerSymbol;
                    return true;
                }
                ConsoleHelper.StdErr(String.Format("运行时错误：执行过程{0}时参数个数错误，应为{1}个参数，实为{2}个参数\n",
                                                   customProcess.Name,
                                                   customProcess.Arguments.Count, realArguments.Count));
                return false;
            }
            ConsoleHelper.StdErr(String.Format("运行时错误：使用过程{0}时还未定义此过程\n", customProcessName));
            return false;
        }


        public static bool ExecuteACommand(IntermediateCode intermediateCode)
        {
            switch (intermediateCode.Operator)
            {
                case "+":
                case "-":
                case "*":
                case "/":
                case "&":
                case "|":
                    return NumberCalculate(intermediateCode);
                case "=":
                case "!=":
                case ">":
                case ">=":
                case "<":
                case "<=":
                    return BoolCalculate(intermediateCode);
                case "!":
                    if (intermediateCode.Arguments.Count != 1)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：执行\"!\"运算时参数个数错误\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.String ||
                        (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable &&
                         GetVariable(intermediateCode.Arguments[0].VariableValue) &&
                         intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.String))
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：执行\"!\"运算时参数类型不为数值\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    //获取数值
                    double valueBool = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                           ? intermediateCode.Arguments[0].NumberValue
                                           : intermediateCode.Arguments[0].VariableValue.NumberValue;
                    if (valueBool != 0 && valueBool != 1)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：只有BOOL型数值0或1才能参与\"!\"运算\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    intermediateCode.Result.Update(valueBool == 1 ? 0 : 1);
                    int index = _symbolList.FindIndex(s => s.Name == intermediateCode.Result.Name);
                    if (index >= 0) //更新符号表
                    {
                        _symbolList[index] = intermediateCode.Result;
                    }
                    break;
                case "to":
                    _customProcessListTop++;
                    break;
                case "#check":
                    if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number ||
                        intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable &&
                        GetVariable(intermediateCode.Arguments[0].VariableValue) &&
                        intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.Number)
                    {
                        //获取数值
                        double valueNum = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                              ? intermediateCode.Arguments[0].NumberValue
                                              : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        if (NumberHelper.CheckInteger(valueNum))
                        {
                            return true;
                        }
                    }
                    ConsoleHelper.StdErr(String.Format("运行时错误：repeat的次数必须为正整数且不能超过15位\n\t错误位置：{0} line {1}\n",
                                                       intermediateCode.FileName, intermediateCode.Line));
                    return false;
                case "make":
                    if (intermediateCode.Arguments.Count != 2)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：执行\"MAKE\"命令时参数个数错误\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    //获取参数名称
                    String name;
                    if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.String) //第一个参数是字符串
                    {
                        String n = intermediateCode.Arguments[0].StringValue;
                        name = n.Substring(1, n.Length - 2);
                    }
                    else if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable && //第一个参数是字符串变量
                             GetVariable(intermediateCode.Arguments[0].VariableValue) &&
                             intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.String)
                    {
                        String n = intermediateCode.Arguments[0].VariableValue.StringValue;
                        name = n.Substring(1, n.Length - 2);
                    }
                    else
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：\"MAKE\"命令的第一个参数必须是字符串\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    name = name.ToLower();
                    if (!StringHelper.IsToken(name))
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：\"MAKE\"命令的第一个参数必须是合法的标识符\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    //获取全局变量列表
                    List<Variable> symbols = _symbolList.GetRange(_symbolList.Count - _symbolNum, _symbolNum);
                    //MAKE产生的新的变量
                    Variable variable;
                    switch (intermediateCode.Arguments[1].TheType)
                    {
                        case Agument.ArgumentType.String: //字符型
                            variable = new Variable(name, intermediateCode.Arguments[1].StringValue);
                            break;
                        case Agument.ArgumentType.Number: //数值型
                            variable = new Variable(name, intermediateCode.Arguments[1].NumberValue);
                            break;
                        default: //赋值为另一个变量的值
                            variable = intermediateCode.Arguments[1].VariableValue;
                            variable.Name = name;
                            break;
                    }
                    if (symbols.FirstOrDefault(s => s.Name == name) == null) //如果没有这个全局变量
                    {
                        _symbolList.Add(variable);
                        _symbolNum++;
                        return true;
                    }
                    //如果有这个全局变量
                    if (variable.TheType == Variable.VariableType.String) //字符串类型的
                    {
                        _symbolList[_symbolList.FindIndex(_symbolList.Count - _symbolNum, v => v.Name == name)].Update(
                            variable.StringValue);
                        return true;
                    }
                    _symbolList[_symbolList.FindIndex(_symbolList.Count - _symbolNum, v => v.Name == name)].Update(
                        variable.NumberValue); //数值型的
                    break;
                case "#=":
                    intermediateCode.Result.TheType = Variable.VariableType.Number;
                    intermediateCode.Result.NumberValue = intermediateCode.Arguments[0].TheType ==
                                                          Agument.ArgumentType.Number
                                                              ? intermediateCode.Arguments[0].NumberValue
                                                              : intermediateCode.Arguments[0].VariableValue.NumberValue;
                    break;
                case "print":
                    if (intermediateCode.Arguments.Count != 1)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数个数错误\n\t错误位置：{1} line {2}\n",
                                                           intermediateCode.Operator, intermediateCode.FileName,
                                                           intermediateCode.Line));
                        return false;
                    }
                    //如果打印的是数字
                    if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number ||
                        (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable &&
                         GetVariable(intermediateCode.Arguments[0].VariableValue) &&
                         intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.Number))
                    {
                        String output = (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                            ? intermediateCode.Arguments[0].NumberValue
                                            : intermediateCode.Arguments[0].VariableValue.NumberValue).ToString();
                        int ind = output.IndexOf('.');
                        if(ind >=0 && ind + 4 < output.Length)
                        {
                            output = output.Substring(0, ind + 5);
                        }
                        TurtleCommand.Print(output);
                        return true;
                    }
                    //如果打印的是字符串
                    if(intermediateCode.Arguments[0].TheType == Agument.ArgumentType.String ||
                        (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable &&
                         intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.String))
                    {
                        String output = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.String
                                            ? intermediateCode.Arguments[0].StringValue
                                            : intermediateCode.Arguments[0].VariableValue.StringValue;
                        TurtleCommand.Print(output.Substring(1, output.Length -2).Replace("\\\"","\"").Replace("\\\\","\\"));
                        return true;
                    }
                    ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数类型不为数值或字符串\n\t错误位置：{1} line {2}\n",
                                                       intermediateCode.Operator, intermediateCode.FileName,
                                                       intermediateCode.Line));
                    return false;
                case "pu":
                    if (CheckArguments(intermediateCode, 0))
                    {
                        TurtleCommand.Pu();
                        return true;
                    }
                    return false;
                case "pd":
                    if (CheckArguments(intermediateCode, 0))
                    {
                        TurtleCommand.Pd();
                        return true;
                    }
                    return false;
                case "cs":
                    if (CheckArguments(intermediateCode, 0))
                    {
                        TurtleCommand.Cs();
                        return true;
                    }
                    return false;
                case "home":
                    if (CheckArguments(intermediateCode, 0))
                    {
                        TurtleCommand.Home();
                        return true;
                    }
                    return false;
                case "fd":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double dis = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.Fd(dis);
                        return true;
                    }
                    return false;
                case "bk":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double dis = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.Bk(dis);
                        return true;
                    }
                    return false;
                case "rt":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double deg = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.Rt(deg * Math.PI / 180);
                        return true;
                    }
                    return false;
                case "lt":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double deg = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.Lt(deg * Math.PI / 180);
                        return true;
                    }
                    return false;
                case "setx":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double pos = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.SetX(pos);
                        return true;
                    }
                    return false;
                case "sety":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double pos = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.SetY(pos);
                        return true;
                    }
                    return false;
                case "setxy":
                    if (CheckArguments(intermediateCode, 2))
                    {
                        double posX = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                          ? intermediateCode.Arguments[0].NumberValue
                                          : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        double posY = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                                          ? intermediateCode.Arguments[1].NumberValue
                                          : intermediateCode.Arguments[1].VariableValue.NumberValue;
                        TurtleCommand.SetXy(posX, posY);
                        return true;
                    }
                    return false;
                case "seth":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double deg = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[0].NumberValue
                                         : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.SetH(deg);
                        return true;
                    }
                    return false;
                case "circle":
                    if (CheckArguments(intermediateCode, 1))
                    {
                        double r = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                       ? intermediateCode.Arguments[0].NumberValue
                                       : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        TurtleCommand.Circle(r);
                        return true;
                    }
                    return false;
                case "circlefill":
                    if (CheckArguments(intermediateCode, 5))
                    {
                        double r = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                       ? intermediateCode.Arguments[0].NumberValue
                                       : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        int color = 0;
                        if (CalculateColor(intermediateCode, 1, ref color)) //如果是合法的颜色值
                        {
                            TurtleCommand.CircleFill(r, color);
                        }
                        return true;
                    }
                    return false;
                case "ellipse":
                    if (CheckArguments(intermediateCode, 2))
                    {
                        double width = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                           ? intermediateCode.Arguments[0].NumberValue
                                           : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        double height = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                                            ? intermediateCode.Arguments[1].NumberValue
                                            : intermediateCode.Arguments[1].VariableValue.NumberValue;
                        TurtleCommand.Ellipse(width, height);
                        return true;
                    }
                    return false;
                case "ellipsefill":
                    if (CheckArguments(intermediateCode, 6))
                    {
                        double width = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                           ? intermediateCode.Arguments[0].NumberValue
                                           : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        double height = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                                            ? intermediateCode.Arguments[1].NumberValue
                                            : intermediateCode.Arguments[1].VariableValue.NumberValue;
                        int color = 0;
                        if (CalculateColor(intermediateCode, 2, ref color)) //如果是合法的颜色值
                        {
                            TurtleCommand.EllipseFill(width, height, color);
                        }
                        return true;
                    }
                    return false;
                case "rect":
                    if (CheckArguments(intermediateCode, 2))
                    {
                        double width = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                           ? intermediateCode.Arguments[0].NumberValue
                                           : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        double height = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                                            ? intermediateCode.Arguments[1].NumberValue
                                            : intermediateCode.Arguments[1].VariableValue.NumberValue;
                        TurtleCommand.Rect(width, height);
                        return true;
                    }
                    return false;
                case "rectfill":
                    if (CheckArguments(intermediateCode, 6))
                    {
                        double width = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                                           ? intermediateCode.Arguments[0].NumberValue
                                           : intermediateCode.Arguments[0].VariableValue.NumberValue;
                        double height = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                                            ? intermediateCode.Arguments[1].NumberValue
                                            : intermediateCode.Arguments[1].VariableValue.NumberValue;
                        int color = 0;
                        if (CalculateColor(intermediateCode, 2, ref color)) //如果是合法的颜色值
                        {
                            TurtleCommand.RectFill(width, height, color);
                        }
                        return true;
                    }
                    return false;
                case "poly":
                    if (CheckArgumentsForPoly(intermediateCode, false))
                    {
                        double[] num = new double[intermediateCode.Arguments.Count];
                        for (int i = 0; i < intermediateCode.Arguments.Count; i++)
                        {
                            num[i] = intermediateCode.Arguments[i].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[i].NumberValue
                                         : intermediateCode.Arguments[i].VariableValue.NumberValue;
                        }
                        TurtleCommand.Poly(num);
                        return true;
                    }
                    return false;
                case "polyfill":
                    if (CheckArgumentsForPoly(intermediateCode, true))
                    {
                        double[] num = new double[intermediateCode.Arguments.Count - 4];
                        for (int i = 0; i < intermediateCode.Arguments.Count - 4; i++)
                        {
                            num[i] = intermediateCode.Arguments[i].TheType == Agument.ArgumentType.Number
                                         ? intermediateCode.Arguments[i].NumberValue
                                         : intermediateCode.Arguments[i].VariableValue.NumberValue;
                        }
                        int color = 0;
                        if (CalculateColor(intermediateCode, intermediateCode.Arguments.Count - 4, ref color)) //如果是合法的颜色值
                        {
                            TurtleCommand.PolyFill(num, color);
                            return true;
                        }
                    }
                    return false;
                case "setfrcolor":
                    if (CheckArguments(intermediateCode, 4))
                    {
                        int color = 0;
                        if (CalculateColor(intermediateCode, 2, ref color)) //如果是合法的颜色值
                        {
                            TurtleCommand.SetFrColor(color);
                            return true;
                        }
                    }
                    return false;
                case "setbkcolor":
                    if (CheckArguments(intermediateCode, 4))
                    {
                        int color = 0;
                        if (CalculateColor(intermediateCode, 2, ref color)) //如果是合法的颜色值
                        {
                            ConsoleHelper.StdErr(
                                String.Format("警告：执行\"{0}\"命令时会清空画板，请保证在开始绘图之前使用此命令\n\t位置：{1} line {2}\n",
                                              intermediateCode.Operator, intermediateCode.FileName,
                                              intermediateCode.Line));
                            TurtleCommand.SetBkColor(color);
                            return true;
                        }
                    }
                    return false;
                default:
                    if (!ExecuteCustomProcess(intermediateCode.Operator, intermediateCode.Arguments))
                    {
                        ConsoleHelper.StdErr(String.Format("\t错误位置：{0} line {1}\n", intermediateCode.FileName,
                                                           intermediateCode.Line));
                        return false;
                    }
                    break;
            }
            return true;
        }

        //执行二元算术逻辑运算
        private static bool NumberCalculate(IntermediateCode intermediateCode)
        {
            if (intermediateCode.Arguments.Count != 2)
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"运算时参数个数错误\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            if (intermediateCode.Arguments.Any(
                agument =>
                agument.TheType == Agument.ArgumentType.String ||
                (agument.TheType == Agument.ArgumentType.Variable &&
                 GetVariable(agument.VariableValue) &&
                 agument.VariableValue.TheType == Variable.VariableType.String)))
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"运算时参数类型不为数值\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            double arg1 = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                              ? intermediateCode.Arguments[0].NumberValue
                              : intermediateCode.Arguments[0].VariableValue.NumberValue;
            double arg2 = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                              ? intermediateCode.Arguments[1].NumberValue
                              : intermediateCode.Arguments[1].VariableValue.NumberValue;
            switch (intermediateCode.Operator)
            {
                case "+":
                    intermediateCode.Result.Update(arg1 + arg2);
                    break;
                case "-":
                    intermediateCode.Result.Update(arg1 - arg2);
                    break;
                case "*":
                    intermediateCode.Result.Update(arg1*arg2);
                    break;
                case "/":
                    if(arg2 == 0)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：除法运算中除数不能为0\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    intermediateCode.Result.Update(arg1/arg2);
                    break;
                case "&":
                    if (arg1 != 0 && arg1 != 1 || arg2 != 0 && arg2 != 1)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：只有BOOL型数值0或1才能参与\"&\"运算\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    intermediateCode.Result.Update(arg1 == 1 && arg2 == 1 ? 1 : 0);
                    break;
                case "|":
                    if (arg1 != 0 && arg1 != 1 || arg2 != 0 && arg2 != 1)
                    {
                        ConsoleHelper.StdErr(String.Format("运行时错误：只有BOOL型数值0或1才能参与\"|\"运算\n\t错误位置：{0} line {1}\n",
                                                           intermediateCode.FileName, intermediateCode.Line));
                        return false;
                    }
                    intermediateCode.Result.Update(arg1 == 0 && arg2 == 0 ? 0 : 1);
                    break;
            }
            int index = _symbolList.FindIndex(s => s.Name == intermediateCode.Result.Name);
            if (index >= 0)//更新符号表
            {
                _symbolList[index] = intermediateCode.Result;
            }
            return true;
        }

        //布尔运算
        private static bool BoolCalculate(IntermediateCode intermediateCode)
        {
            if (intermediateCode.Arguments.Count != 2)
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"运算时参数个数错误\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            if (!intermediateCode.Arguments.All( //都是字符串
                    agument =>
                    agument.TheType == Agument.ArgumentType.String ||
                    (agument.TheType == Agument.ArgumentType.Variable &&
                     GetVariable(agument.VariableValue) &&
                     agument.VariableValue.TheType == Variable.VariableType.String)) &&
                !intermediateCode.Arguments.All( //或者都是数值
                    agument =>
                    agument.TheType == Agument.ArgumentType.Number ||
                    (agument.TheType == Agument.ArgumentType.Variable &&
                     GetVariable(agument.VariableValue) &&
                     agument.VariableValue.TheType == Variable.VariableType.Number)))
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"运算时参数类型不都为数值或者不都为字符串\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            //如果是数值
            if (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number ||
                (intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Variable &&
                    GetVariable(intermediateCode.Arguments[0].VariableValue) &&
                    intermediateCode.Arguments[0].VariableValue.TheType == Variable.VariableType.Number))
            {
                double arg1 = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.Number
                              ? intermediateCode.Arguments[0].NumberValue
                              : intermediateCode.Arguments[0].VariableValue.NumberValue;
                double arg2 = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.Number
                              ? intermediateCode.Arguments[1].NumberValue
                              : intermediateCode.Arguments[1].VariableValue.NumberValue;
                switch (intermediateCode.Operator)
                {
                    case "=":
                        intermediateCode.Result.Update(arg1 == arg2 ? 1 : 0);
                        break;
                    case "!=":
                        intermediateCode.Result.Update(arg1 != arg2 ? 1 : 0);
                        break;
                    case ">":
                        intermediateCode.Result.Update(arg1 > arg2 ? 1 : 0);
                        break;
                    case ">=":
                        intermediateCode.Result.Update(arg1 >= arg2 ? 1 : 0);
                        break;
                    case "<":
                        intermediateCode.Result.Update(arg1 < arg2 ? 1 : 0);
                        break;
                    case "<=":
                        intermediateCode.Result.Update(arg1 <= arg2 ? 1 : 0);
                        break;
                }
                return true;
            }
            //如果是字符串之间的比较
            String argS1 = intermediateCode.Arguments[0].TheType == Agument.ArgumentType.String
                              ? intermediateCode.Arguments[0].StringValue
                              : intermediateCode.Arguments[0].VariableValue.StringValue;
            String argS2 = intermediateCode.Arguments[1].TheType == Agument.ArgumentType.String
                              ? intermediateCode.Arguments[1].StringValue
                              : intermediateCode.Arguments[1].VariableValue.StringValue;
            switch (intermediateCode.Operator)
            {
                case "=":
                    intermediateCode.Result.Update(argS1 == argS2 ? 1 : 0);
                    break;
                case "!=":
                    intermediateCode.Result.Update(argS1 != argS2 ? 1 : 0);
                    break;
                case ">":
                    intermediateCode.Result.Update(String.CompareOrdinal(argS1, argS2) > 0 ? 1 : 0);
                    break;
                case ">=":
                    intermediateCode.Result.Update(String.CompareOrdinal(argS1, argS2) >= 0 ? 1 : 0);
                    break;
                case "<":
                    intermediateCode.Result.Update(String.CompareOrdinal(argS1, argS2) < 0 ? 1 : 0);
                    break;
                case "<=":
                    intermediateCode.Result.Update(String.CompareOrdinal(argS1, argS2) <= 0 ? 1 : 0);
                    break;
            }
            int index = _symbolList.FindIndex(s => s.Name == intermediateCode.Result.Name);
            if (index >= 0)//更新符号表
            {
                _symbolList[index] = intermediateCode.Result;
            }
            return true;
        }
    
        //查符号表获取变量的值
        private static bool GetVariable(Variable variable)
        {
            if(variable.Name[0] == '#')
            {
                return true;
            }
            Variable v = _symbolList.FirstOrDefault(s => s.Name == variable.Name);
            if(v == null)
            {
                return false;
            }
            variable.NumberValue = v.NumberValue;
            variable.StringValue = v.StringValue;
            variable.TheType = v.TheType;
            return true;
        }

        //为绘图命令检查参数个数、参数类型，并且装填参数
        private static bool CheckArguments(IntermediateCode intermediateCode, int num)
        {
            if (intermediateCode.Arguments.Count != num)
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数个数错误\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            if (intermediateCode.Arguments.Any(
                agument =>
                agument.TheType == Agument.ArgumentType.Number ||
                (agument.TheType == Agument.ArgumentType.Variable &&
                 GetVariable(agument.VariableValue) &&
                 agument.VariableValue.TheType == Variable.VariableType.Number)))
            {
                return true;
            }
            ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数类型不为数值\n\t错误位置：{1} line {2}\n",
                                               intermediateCode.Operator, intermediateCode.FileName,
                                               intermediateCode.Line));
            return false;
        }

        //为多边形命令检查参数个数、参数类型，并且装填参数
        private static bool CheckArgumentsForPoly(IntermediateCode intermediateCode, bool fill)
        {
            if (fill && (intermediateCode.Arguments.Count % 2 != 0 || intermediateCode.Arguments.Count < 10) ||
                !fill && (intermediateCode.Arguments.Count % 2 != 0 || intermediateCode.Arguments.Count < 6))
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数个数错误\n\t错误位置：{1} line {2}\n",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            if (intermediateCode.Arguments.Any(
                agument =>
                agument.TheType == Agument.ArgumentType.Number ||
                (agument.TheType == Agument.ArgumentType.Variable &&
                 GetVariable(agument.VariableValue) &&
                 agument.VariableValue.TheType == Variable.VariableType.Number)))
            {
                return true;
            }
            ConsoleHelper.StdErr(String.Format("运行时错误：执行\"{0}\"命令时参数类型不为数值\n\t错误位置：{1} line {2}\n",
                                               intermediateCode.Operator, intermediateCode.FileName,
                                               intermediateCode.Line));
            return false;
        }
    
        //计算颜色的值
        private static bool CalculateColor(IntermediateCode intermediateCode, int i, ref int color)
        {
            double colorA = intermediateCode.Arguments[i].TheType == Agument.ArgumentType.Number
                                ? intermediateCode.Arguments[i].NumberValue
                                : intermediateCode.Arguments[i].VariableValue.NumberValue;
            double colorR = intermediateCode.Arguments[i + 1].TheType == Agument.ArgumentType.Number
                                ? intermediateCode.Arguments[i + 1].NumberValue
                                : intermediateCode.Arguments[i + 1].VariableValue.NumberValue;
            double colorG = intermediateCode.Arguments[i + 2].TheType == Agument.ArgumentType.Number
                                ? intermediateCode.Arguments[i + 2].NumberValue
                                : intermediateCode.Arguments[i + 2].VariableValue.NumberValue;
            double colorB = intermediateCode.Arguments[i + 3].TheType == Agument.ArgumentType.Number
                                ? intermediateCode.Arguments[i + 3].NumberValue
                                : intermediateCode.Arguments[i + 3].VariableValue.NumberValue;
            if (!NumberHelper.CheckInteger(colorR) || !NumberHelper.CheckInteger(colorG) ||
                !NumberHelper.CheckInteger(colorB) || !NumberHelper.CheckInteger(colorA))
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：{0}的颜色值参数必须为正整数\n\t错误位置：{1} line {2}",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            if (colorA < 0 || colorA > 255 || colorR < 0 || colorR > 255 || colorG < 0 || colorG > 255 || colorB < 0 || colorB > 255) //如果是非法的颜色值
            {
                ConsoleHelper.StdErr(String.Format("运行时错误：{0}的颜色值参数必须为在0-255之间\n\t错误位置：{1} line {2}",
                                                   intermediateCode.Operator, intermediateCode.FileName,
                                                   intermediateCode.Line));
                return false;
            }
            color = (int) colorA <<24 | (int) colorR << 16 | (int) colorG << 8 | (int) colorB;
            return true;
        }
    }
}
